package com.wenwenli.boot.mvc.servlet;

import com.wenwenli.boot.annotation.Controller;
import com.wenwenli.boot.annotation.PathVariable;
import com.wenwenli.boot.annotation.RequestMapping;
import com.wenwenli.boot.annotation.RequestParam;
import com.wenwenli.boot.beans.BeanDefinition;
import com.wenwenli.boot.context.ApplicationContext;
import com.wenwenli.boot.context.SpringApplication;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
 * @Author 写不完的BUG
 * @Description  springMvc 请求路由servlet
 * @Date  2019-04-15
 **/
public class SpringMvcRoutingServlet extends HttpServlet {

    private ApplicationContext applicationContext;
    /**
     * url与method对应关系
     */
    private Map<String, Method> urlMethod = new HashMap();
    /**
     * url与controller对应的关系
     */
    private Map<String, Object> urlBean = new HashMap();

    public SpringMvcRoutingServlet() {
        super();
    }

    @Override
    public void init() throws ServletException {
        String basePackage = this.getInitParameter("basePackage");
        if(!StringUtils.isBlank(basePackage)){
            try {
                SpringApplication.run(basePackage);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        initWebRouting();
        super.init();
    }

    private void initWebRouting() {
        applicationContext = ApplicationContext.getInstance();
        Map<String, BeanDefinition> applicationContextBeans = applicationContext.getApplicationContextBeans();
        Iterator<String> iterator = applicationContextBeans.keySet().iterator();
        while (iterator.hasNext()) {
            String beanName = iterator.next();
            Object target = applicationContextBeans.get(beanName).getTarget();
            Class<?> cls = target.getClass();
            if (cls.isAnnotationPresent(Controller.class)) {
                parseRoutingInfo(cls);
            }
        }

    }

    private void parseRoutingInfo(Class<?> cls) {
        RequestMapping requestMapping = cls.getAnnotation(RequestMapping.class);
        String beanUrl = "";
        if (null != requestMapping) {
            beanUrl = requestMapping.value();
        }
        Method[] methods = cls.getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            if (method.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                String methodUrl = annotation.value();
                if (methodUrl.startsWith("/")) {
                    urlBean.put(beanUrl + methodUrl, applicationContext.getBean(cls));
                    urlMethod.put(beanUrl + methodUrl, method);
                } else {
                    urlBean.put(beanUrl + "/" + methodUrl, applicationContext.getBean(cls));
                    urlMethod.put(beanUrl + "/" + methodUrl, method);
                }
            }
        }

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String servletPath = req.getServletPath();
        Method method = urlMethod.get(servletPath);
        Object o = urlBean.get(servletPath);
        invokeMethod(o, method, resp, req);
    }
    public void invokeMethod(Object bean, Method method, HttpServletResponse response, HttpServletRequest request) {
        Parameter[] parameters = method.getParameters();
        Object[] value = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            if (parameter.getType().getName().equalsIgnoreCase(HttpServletResponse.class.getName())) {
                value[i] = response;
                continue;
            }
            if (parameter.getType().getName().equalsIgnoreCase(HttpServletRequest.class.getName())) {
                value[i] = request;
                continue;
            }
            String parameterName = parameter.getName();
            if (parameter.isAnnotationPresent(RequestParam.class)) {
                boolean mark = "".equalsIgnoreCase(parameter.getAnnotation(RequestParam.class).value());
                if (mark) {
                    value[i] = request.getParameter(parameterName);
                } else {
                    value[i] = request.getParameter(parameter.getAnnotation(RequestParam.class).value());
                }
                continue;
            }

            //什么注解也没有写则按照参数名字获取值
            value[i] = request.getParameter(parameterName);
        }
        try {
            method.invoke(bean,value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
